home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / LANG / C / LIB / UNIXLIB37B / !UnixLib37 / src / signal / c / sleep < prev   
Text File  |  1996-11-09  |  3KB  |  114 lines

  1. /****************************************************************************
  2.  *
  3.  * $Source: /unixb/home/unixlib/source/unixlib37/src/signal/c/RCS/sleep,v $
  4.  * $Date: 1996/10/30 22:04:51 $
  5.  * $Revision: 1.1 $
  6.  * $State: Rel $
  7.  * $Author: unixlib $
  8.  *
  9.  * $Log: sleep,v $
  10.  * Revision 1.1  1996/10/30 22:04:51  unixlib
  11.  * Initial revision
  12.  *
  13.  ***************************************************************************/
  14.  
  15. static const char rcs_id[] = "$Id: sleep,v 1.1 1996/10/30 22:04:51 unixlib Rel $";
  16.  
  17. /* signal.c.sleep: Written by Nick Burrett, 6 October 1996.  */
  18.  
  19. #include <signal.h>
  20. #include <time.h>
  21. #include <unistd.h>
  22. #include <errno.h>
  23.  
  24. /* SIGALRM signal handler for `sleep'.  This does nothing but return,
  25.    but SIG_IGN isn't supposed to break `pause'.  */
  26. static void sleep_handler (int sig)
  27. {
  28.   sig = sig;
  29.   return;
  30. }
  31.  
  32. /* Make the process sleep for SECONDS seconds, or until a signal arrives
  33.    and is not ignored.  The function returns the number of seconds less
  34.    than SECONDS which it actually slept (zero if it slept the full time).  */
  35. unsigned int sleep (unsigned int seconds)
  36. {
  37.   unsigned int remaining, slept;
  38.   time_t before, after;
  39.   sigset_t set, oset;
  40.   struct sigaction act, oact;
  41.   int save = errno;
  42.  
  43.   if (seconds == 0)
  44.     return 0;
  45.  
  46.   /* Block SIGALRM signals while frobbing the handler.  */
  47.   sigemptyset (&set);
  48.   if (sigaddset (&set, SIGALRM) || sigprocmask (SIG_BLOCK, &set, &oset))
  49.     return seconds;
  50.  
  51.   act.sa_handler = sleep_handler;
  52.   act.sa_flags = 0;
  53.   sigemptyset (&act.sa_mask);
  54.   if (sigaction (SIGALRM, &act, &oact))
  55.     return seconds;
  56.  
  57.   before = time ((time_t *) NULL);
  58.   remaining = alarm (seconds);
  59.  
  60. #ifdef DEBUG
  61.   printf ("sleep: Set up an alarm for %d seconds time.\n", seconds);
  62. #endif
  63.  
  64.   if (remaining > 0 && remaining < seconds)
  65.     {
  66.       /* The user's alarm will expire before our own would.
  67.      Restore the user's signal action state and let his alarm happen.  */
  68.       sigaction (SIGALRM, &oact, (struct sigaction *) NULL);
  69.       alarm (remaining);    /* Restore sooner alarm.  */
  70. #ifdef DEBUG
  71.       printf ("sleep: A user alarm existed. Wait %d secs for that instead\n", remaining);
  72. #endif
  73.       sigsuspend (&oset);    /* Wait for it to go off.  */
  74. #ifdef DEBUG
  75.       printf ("sleep: Alarm has now gone off. Continuing with execution\n");
  76. #endif
  77.       after = time ((time_t *) NULL);
  78.     }
  79.   else
  80.     {
  81.       /* Atomically restore the old signal mask
  82.      (which had better not block SIGALRM),
  83.      and wait for a signal to arrive.  */
  84. #ifdef DEBUG
  85.       printf ("sleep: Waiting for the alarm\n");
  86. #endif
  87.       sigsuspend (&oset);
  88. #ifdef DEBUG
  89.       printf ("sleep: Alarm has now gone off. Continuing with execution\n");
  90. #endif
  91.       after = time ((time_t *) NULL);
  92.  
  93.       /* Restore the old signal action state.  */
  94.       sigaction (SIGALRM, &oact, (struct sigaction *) NULL);
  95.     }
  96.  
  97.   /* Notice how long we actually slept.  */
  98.   slept = (unsigned int)(after - before);
  99.  
  100.   /* Restore the user's alarm if we have not already past it.
  101.      If we have, be sure to turn off the alarm in case a signal
  102.      other than SIGALRM was what woke us up.  */
  103.   alarm (remaining > slept ? remaining - slept : 0);
  104.  
  105.   /* Restore the original signal mask.  */
  106.   sigprocmask (SIG_SETMASK, &oset, (sigset_t *) NULL);
  107.  
  108.   /* Restore the `errno' value we started with.
  109.      Some of the calls we made might have failed, but we don't care.  */
  110.   errno = save;
  111.  
  112.   return slept > seconds ? 0 : seconds - slept;
  113. }
  114.